import os
import threading
import re
from datetime import datetime
import time, yaml, json, paramiko
import subprocess
from flask import Blueprint, request, send_file,session,request, jsonify
from Logger import logger, logger_config
from utils import MyResponse, get_global_config, get_local_ip, handle_exception, handle_success, to_lower_camel_case
from db_handler import db_handler

buildTask = Blueprint('buildTask', __name__)


# 传参：{"projectName":"ZhongTaiv850","isMonitor":false,"distributedValue":["10.58.10.4"],"scenarioNames":["TC03_根据单位和时间查询会计科目信息"],"bindSlaverIp":[]}
# 根据勾选的场景修改YAML文件
@buildTask.route('/file/generateBuildYaml', methods=['POST'])
def generate_build_yaml():
    try:
        # 获取前端传来的JSON数据
        params = request.json
        root_path = get_global_config()['rootPath']
        project_name = params["projectName"]
        project_dir = os.path.join(root_path, project_name)
        yaml_path = os.path.join(project_dir, f"{project_name}.yaml")
        yaml_run_path = os.path.join(project_dir, f"{project_name}_build.yaml")

        # 读取旧的YAML文件内容
        with open(yaml_path, "r", encoding='utf-8') as old_file:
            yaml_content = yaml.safe_load(old_file)

        # 处理多个 scenarioName
        scenario_names = params.get("scenarioNames", [])
        new_execution = [item for item in yaml_content.get('execution', [])
                         if item.get("scenario") in scenario_names]

        # 保持其他内容与旧的 YAML 文件一致
        new_yaml_content = yaml_content.copy()
        new_yaml_content['execution'] = new_execution

        # 将更新后的YAML内容写入到文件中
        with open(yaml_run_path, "w", encoding='utf-8', ) as new_file:
            yaml.safe_dump(new_yaml_content, new_file, default_flow_style=False, allow_unicode=True, sort_keys=False)

    except Exception as err:
        return handle_exception(err, "程序异常")
    else:
        return handle_success(new_yaml_content, "success")



# 定义一个函数来序列化 datetime 对象
def default_serializer(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    raise TypeError(f"Type {obj.__class__.__name__} not serializable")

# 传参：projectName、distributedValue、scenarioNames、beginDate、beginTime、
# 返回：{
#     "data": {
#         "content": "压测机：[]；每个用例执行：30s；测试用例：100并发【TC01_登录】，100并发【TC02_填写出差申请】",
#         "creater_time": "Fri, 14 Mar 2025 11:26:10 GMT",
#         "status": "0",
#         "task_name": "test20250314112610"
#     },
@buildTask.route('/createTask', methods=['POST'])
def create_task():
    try:
        params = request.json
        project_name = params["projectName"]
        root_path = get_global_config()['rootPath']
        jmeter_path = get_global_config()['jmeterPath']
        target_ip = params["distributedValue"]
        scenario_names = params.get("scenarioNames", [])
        jtlpath = os.path.join(root_path, project_name, 'jtl')
        runtohtml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'RunTohtml.py')
        yaml_file_build = os.path.join(root_path, project_name, project_name) + "_build.yaml"
        run_bat_path = os.path.join(root_path, project_name, project_name) + "runtask.bat"

        #在项目路径下创建个bat文件运行测试框架
        if os.path.exists(run_bat_path):
            os.remove(run_bat_path)

        lines_to_write = [
            "@echo off",
            "echo Starting the task...",
            "REM This is a comment line",
            r"D:\apache-jmeter-5.4.1\bin\jmeter.bat",
            # f"rd /s /q {jtlpath}",
            # f"bzt -q {yaml_file_build}",
            # "python  " + runtohtml_path + ' ' + jmeter_path + ' ' + jtlpath + ' ' + yaml_file_build + ' ' + str(project_id)+ ' ' + str(task_run_id),
            # "python  " + runtohtml_path + ' ' + jmeter_path + ' ' + jtlpath + ' ' + yaml_file_build,
            "echo Task completed."
        ]

        with open(run_bat_path, 'w', encoding='utf-8') as batch_file:
            for line in lines_to_write:
                batch_file.write(line + '\n')

        #指定时间自动执行该bat文件
        current_datetime = datetime.now()
        formatted_string = current_datetime.strftime("%Y%m%d%H%M%S")
        task_name = f"test{formatted_string}"
        task_time = params['runtime']
        dt = datetime.strptime(task_time, "%Y-%m-%dT%H:%M:%S.%fZ")
        # 获取日期部分，格式为 "YYYY/MM/DD"
        date_str = dt.strftime("%Y/%m/%d") # 2025/03/04
        # 获取时间部分，格式为 "HH:MM:SS"
        time_str = dt.strftime("%H:%M:%S") # 15:45:00

        command = (
            f"schtasks /create  /tn \"{task_name}\" "
            f"/tr \"{run_bat_path}\" "
            f"/sc once /sd {date_str} /st {time_str}"
        )
        print(command)

        # 使用 subprocess 运行命令
        try:
            subprocess.run(command, check=True, shell=True)
            logger.info("任务已成功创建")
        except subprocess.CalledProcessError as e:
            logger.error(f"执行失败: {e}")
            return handle_exception(e, "任务创建失败")

        # 向数据库插入运行任务记录
        project_id = db_handler.execute_query("SELECT id FROM project WHERE project_name = %s", (project_name,))[0][
            "id"]
        slaver_ip = ", ".join(f"'{item}'" for item in target_ip)
        run_scenarios = ", ".join(f"'{item}'" for item in scenario_names)
        run_user = session["loginname"]
        run_ip = session["client_ip"]
        # run_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
        run_time = dt.strftime('%Y-%m-%d %H:%M:%S')
        insert_sql = "INSERT INTO buildtask (project_id, task_name, slaver_ip, run_ip, run_user, run_time, run_scenarios, status) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)"
        insert_value = (project_id, task_name, slaver_ip, run_ip, run_user, run_time, run_scenarios, 'planning')
        db_handler.insert(insert_sql, insert_value)
    except Exception as err:
        return handle_exception(err, "程序异常")
    else:
        return handle_success("success", "success")


# 停止接口
# 传参：{	"taskName":"test202503067105450"}
# 返回：{}
@buildTask.route('/cancelTask', methods=['POST'])
def cancel_task():
    try:
        params = request.json
        task_name = params.get('taskName')

        command = f'schtasks /delete /tn {task_name} /f'
        subprocess.run(command, check=True, shell=True)
        logger.info(f"计划的任务:{task_name}被成功删除")

        del_sql = 'DELETE FROM buildtask WHERE task_name = %s'
        db_handler.delete(del_sql, (task_name,))

    except Exception as err:
        return handle_exception(err, "程序异常")
    else:
        return handle_success("成功取消任务", "success")

# 查询
@buildTask.route('/getPlanlist', methods=['POST'])
def get_plan_list():
    try:
        # 获取请求参数
        params = request.json
        # creater = params.get("creater", "")
        project_name = params.get("projectName", "")
        pageNum = int(params.get("pageNum", 1))  # 默认第一页
        pageSize = int(params.get("pageSize", 20))  # 默认每页20条

        start_index = (pageNum - 1) * pageSize
        project_name_like = f"%{project_name}%"
        # creater_like = f"%{creater}%"

        select_query = "SELECT tr.*,p.project_name FROM buildtask tr JOIN project p ON tr.project_id = p.id WHERE p.project_name LIKE %s AND tr.status = 'planning' ORDER BY tr.run_time DESC LIMIT %s, %s;"

        results = db_handler.execute_query(select_query, (project_name_like, start_index, pageSize))
        print(results)

        # 格式化 runtime 字段（datetime 对象）
        for project in results:
            if 'run_time' in project and isinstance(project['run_time'], datetime):
                project['run_time'] = project['run_time'].strftime('%Y-%m-%d %H:%M:%S')

        # 将字典键从蛇形命名转换为小驼峰命名
        transformed_project_data = [
            {to_lower_camel_case(k): v for k, v in project.items()}
            for project in results
        ]

        # 获取总条目数
        count_query = "SELECT COUNT(*) as total FROM buildtask tr JOIN project p ON tr.project_id = p.id WHERE p.project_name LIKE %s AND tr.status = 'planning'"
        total_count = db_handler.execute_query(count_query, (project_name_like,))[0]['total']


        # 构造返回结果
        result = {
            "list": transformed_project_data,
            "total": total_count
        }
        return handle_success(result, "success")
    except Exception as err:
        return handle_exception(err, "程序异常")

# 修改定时任务时间
@buildTask.route('/modifyTaskTime', methods=['POST'])
def modify_task_time():
    try:
        params = request.json
        task_name = params.get('taskName')  # 定时任务的名称
        new_runtime = params.get('runtime')  # 新的运行时间，格式为 "yyyy-MM-ddTHH:mm:ss.000Z"
        project_name = params["projectName"]
        root_path = get_global_config()['rootPath']
        run_bat_path = os.path.join(root_path, project_name, project_name) + "runtask.bat"

        # 将新的时间转换为合适的格式
        dt = datetime.strptime(new_runtime, "%Y-%m-%dT%H:%M:%S.000Z")
        date_str = dt.strftime("%Y/%m/%d")  # 获取日期部分，格式为 "YYYY/MM/DD"
        time_str = dt.strftime("%H:%M:%S")  # 获取时间部分，格式为 "HH:MM:SS"

        # # 使用 schtasks 修改任务时间
        # command = f'runas /user:Administrator "schtasks /change /tn \"{task_name}\" /st {time_str} /sd {date_str}"'
        #
        # try:
        #     subprocess.run(command, check=True, shell=True)
        #     logger.info(f"任务 {task_name} 的时间已成功修改为 {date_str} {time_str}")
        # except subprocess.CalledProcessError as e:
        #     logger.error(f"修改任务时间失败: {e}")
        #     return handle_exception(e, "修改任务时间失败")
        command = f'schtasks /delete /tn {task_name} /f'
        subprocess.run(command, check=True, shell=True)
        logger.info(f"计划的任务:{task_name}被成功删除")
        command = (
            f"schtasks /create  /tn \"{task_name}\" "
            f"/tr \"{run_bat_path}\" "
            f"/sc once /sd {date_str} /st {time_str}"
        )
        print(command)

        # 使用 subprocess 运行命令
        try:
            subprocess.run(command, check=True, shell=True)
            logger.info("任务已成功创建")
        except subprocess.CalledProcessError as e:
            logger.error(f"执行失败: {e}")
            return handle_exception(e, "任务创建失败")


        # 更新数据库中的任务时间
        run_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
        update_sql = "UPDATE taskrun SET run_time = %s WHERE task_name = %s"
        update_value = (run_time, task_name)
        db_handler.update(update_sql, update_value)

    except Exception as err:
        return handle_exception(err, "程序异常")
    else:
        return handle_success("任务时间已成功修改", "success")
